<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2015/7/1
 * Time: 21:52
 */

namespace Common\Model;

/**
 * 地区模型
 * Class AreaModel
 * @package Common\Model
 */
class AreaModel extends CommonModel {
    protected $tableName = 'area';
    protected $redisDb = 7;
    private $area_key = 'cgf_area_data';
    private $area_json_key = 'cgf_area_json_data';
    private $valid_city_data = 'cgf_area_city_data';
    private $indexField = 'area_code';

    /**
     * 根据地区编码获取下级地区，若为空，则获取一级，即省份
     * @param string $areacode
     */
    public function getAreaList($areacode=''){
        $data = S(C('CACHE_KEY.area_prefix').$areacode);
        if(empty($data)){
            $map = array();
            if($areacode){
                $province = substr($areacode,0,2);//省
                $city = substr($areacode,0,4);//市

                if($areacode==$province.'0000'){
                    $map['area_code'] = array(array('like',$province.'%00'),array('neq',$province.'0000'),'and');
                } else if($areacode==$city.'00'){
                    $map['area_code'] = array(array('like',$city.'%'),array('neq',$city.'00'),'and');
                } else {
                    return false;
                }
            } else {
                $map['area_code'] = array('like','%0000');
            }
            
            $data = $this->where($map)->field('short,area_code')->select();
            S(C('CACHE_KEY.area_prefix').$areacode,$data);
        }

        return $data;
    }

    /**
     * 获取地区名字
     * @param $code 地区编码，6位数字，多个由英文逗号隔开
     * @param int $layer 获取层级，1=获取一级（省级或市级或县级），2=获取两级（省市），3=获取三级（省市县），即全部
     * @param string $delimiter 分隔符
     * @param int $type 获取具体级数，$layer=1时有效，
     * $layer=1时，$type=1 获取省；$type=2 获取市；$type=3 获取县
     */
    public function getFullNameByAreaCode($code,$layer=3,$delimiter='',$type=1){
        if(empty($code) || empty($layer)) return '';

        $data = $this->getAreaData();

        $codeArr = explode(',',$code);
        $ret = array();
        foreach($codeArr as $county){
            /*
             * $province 省级
             * $city 市级
             * $county 县级
             */
            $province = substr($county,0,2);//省
            $province .= '0000';
            $city = substr($county,0,4);//市
            $city .= '00';

            //若获取全名的地区编码与省名相同，直接返回省名即可
            if($province==$county){
                $ret[] = $data[$county]['name'];
                continue;
            }

            switch(intval($layer)){
                case 1:
                    if($type==1){
                        $ret[] = $data[$province]['name'];
                    } else if($type==2) {
                        $ret[] = $data[$city]['name'];
                    } else {
                        $ret[] = $data[$county]['name'];
                    }
                    break;

                case 2:
                    if($province==$county){
                        $ret[] = $data[$county]['name'];
                    } else {
                        $ret[] = $data[$province]['name'].$delimiter.$data[$city]['name'];
                    }
                    break;

                default:
                    if($province==$county){
                        $ret[] = $data[$county]['name'];
                    } else if($city==$county){
                        $ret[] = $data[$province]['name'].$delimiter.$data[$county]['name'];
                    } else {
                        $ret[] = $data[$province]['name'].$delimiter.$data[$city]['name'].$delimiter.$data[$county]['name'];
                    }
            }
        }

        return implode(',',$ret);
    }

    /**
     * 获取地区数据
     * @return array|bool|mixed|string
     */
    public function getAreaData(){
        $data = S($this->area_key);

        if(empty($data)){
            $data = $this->_getAreaData();
        } else {
            $data = unserialize($data);
        }

        return $data;
    }

    private function _getAreaData(){
        $list = $this->field(true)->select();

        $data = array();
        foreach($list as $val){
            $data[$val['area_code']] = $val;
        }

        S($this->area_key,serialize($data));

        return $data;
    }

    /**
     * 清除地区缓存
     */
    public function clearCache(){
        $this->_getAreaData();
        $this->_getAreaTreeData();
        $this->_getAllValidCity();
        updateCateDBJSFile('area');
    }

    /**
     * 获取地区分级数据
     * @return array|bool|mixed|string
     */
    public function getAreaTreeData(){
        //$list = S('area_category_data');
        $list = S($this->area_json_key);

        if(!$list){
            $list = $this->_getAreaTreeData();
        } else {
            $list = unserialize($list);
        }

        return $list;
    }

    public function getAreaDataInJson(){
        $data[] = $this->getAreaTreeData();

        return json_encode($data);
    }

    private function _getAreaTreeData(){
        $result = $this->order('sort asc')->select();
        $list = $this->get_node_tree($result);

        S($this->area_json_key,serialize($list));

        return $list;
    }

    /**
     * 获取省份编码
     * @param $areacode
     * @return string
     */
    public function getProvinceCode($areacode){
        static $provinceCode = array();
        
        if(!$provinceCode || !isset($provinceCode[$areacode])){
            $provinceCode[$areacode] = substr($areacode,0,2).'0000';
        }
        return $provinceCode[$areacode];
    }

    private function getParentCode($areacode){
        //310110
        $province = substr($areacode,0,2);//省
        $province .= '0000';
        $city = substr($areacode,0,4);//市
        $city .= '00';
        $county = $areacode;//县

        if($areacode==$province){
            return 0;
        } else if($areacode==$city){
            return $province;
        } else if($areacode==$county){
            return $city;
        } else {
            return 0;
        }
    }

    private function getParentCodeInfo($areacode){
        $province = substr($areacode,0,2);//省
        $province .= '0000';
        $city = substr($areacode,0,4);//市
        $city .= '00';
        $county = $areacode;//县

        if($areacode == $province){
            return array('code'=>0,'level'=>1);
        } else if($areacode == $city){
            return array('code'=>$province,'level'=>2);
        } else if($areacode == $county){
            return array('code'=>$city,'level'=>3);
        } else {
            return array('code'=>0,'level'=>1);
        }
    }

    //生成树形结构数据
    protected function get_node_tree($node_db, $node_list='', $level=0) {
        if(empty($node_db)){
            return ;
        }
        //预处理
        if(empty($node_list)) {
            foreach($node_db as $val) {
                $node_list[$this->getParentCode($val['area_code'])][$val['area_code']] = $val;
            }
            return $this->get_node_tree($node_list[0], $node_list, $level);
        }
        //var_dump($node_list[0]);exit;
        //输出树形结构
        $node = array();
        foreach($node_db as $val) {
            $val['level'] = $level;
            if(isset($node_list[$val['area_code']]) && !empty($node_list[$val['area_code']])) {
                $val['level'] = $level;
                $val['child'] = $this->get_node_tree($node_list[$val['area_code']], $node_list, $level+1);
                //var_dump($val);exit;
            }
            $node[$val['area_code']] = $val;
        }
        return $node;
    }

    public function getAreaIdJsonData($field='id'){
        $result = $this->field('id,area_code,name,short')->order('sort asc')->select();
        $list = $this->get_node_id_tree($field,$result);

        return $list;
    }

    protected function get_node_id_tree($field='id',$node_db, $node_list='', $level=0) {
        if(empty($node_db)){
            return ;
        }
        //预处理
        if(empty($node_list)) {
            foreach($node_db as $val) {
                $node_list[$this->getParentCode($val['area_code'])][$val['area_code']] = $val;
            }
            return $this->get_node_id_tree($field,$node_list[0], $node_list, $level);
        }
        //var_dump($node_list[0]);exit;
        //输出树形结构
        $node = array();
        foreach($node_db as $val) {
            $val['level'] = $level;
            if(isset($node_list[$val['area_code']]) && !empty($node_list[$val['area_code']])) {
                $val['level'] = $level;
                $val['child'] = $this->get_node_id_tree($field,$node_list[$val['area_code']], $node_list, $level+1);
                //var_dump($val);exit;
            }
            $node[$val[$field]] = $val;
        }
        return $node;
    }

    public function getCityCodeByName($city){
        $map = array();
        $map['name'] = array('like',$city.'%');
        $map['area_code'] = array('like','%00');

        return M('Area')->where($map)->order('id desc')->getField('area_code');
    }

    public function sort($id,$type){
        if(empty($id)) return false;

        $areacode = $this->where('id='.$id)->getField('area_code');
        $parentCodeInfo = $this->getParentCodeInfo($areacode);

        $codeMap = array();

        switch($parentCodeInfo['level']){
            case 1:
                $codeMap[] = array('like','%0000');
                break;

            case 2:
                $codeMap[] = array('neq',$parentCodeInfo['code']);
                $codeMap[] = array('like',substr($parentCodeInfo,0,2).'%');
                break;

            case 3:
                $codeMap[] = array('neq',$parentCodeInfo['code']);
                $codeMap[] = array('like',substr($parentCodeInfo,0,4).'%');
                break;
        }
        $codeMap[]  = 'and';

        $map = array();
        $map['area_code'] = $codeMap;
        unset($codeMap);
        $data = $this->field('id, sort')->where($map)->order('sort ASC')->select();

        // 存储前后值
        $before = $in = $after = array();
        $keys = $this->getSubByKey($data, 'id');
        $key = array_search($id, $keys);
        $in = $data[$key];
        if($key == 0) {
            $after = $data[$key + 1];
        } else if($key == count($data)) {
            $before = $data[$key - 1];
        } else {
            $before = $data[$key - 1];
            $after = $data[$key + 1];
        }
        // 判断类型
        $this->startTrans();
        switch($type) {
            case 1:
                if(!empty($before)) {
                    $res_1 = $this->where('id='.$id)->setField('sort', $before['sort']);
                    $res_2 = $this->where('id='.$before['id'])->setField('sort', $in['sort']);
                }
                break;
            case 2:
                if(!empty($after)) {
                    $res_1 = $this->where('id='.$id)->setField('sort', $after['sort']);
                    $res_2 = $this->where('id='.$after['id'])->setField('sort', $in['sort']);
                }
                break;

            default:
                $this->rollback();
                return false;
        }

        if($res_1 && $res_2){
            $this->commit();
            $this->clearCache();
            return true;
        } else {
            $this->rollback();
            return false;
        }

        return $result;
    }

    /**
     * 取一个二维数组中的每个数组的固定的键知道的值来形成一个新的一维数组
     * @param $pArray 一个二维数组
     * @param $pKey 数组的键的名称
     * @return 返回新的一维数组
     */
    protected function getSubByKey($pArray, $pKey="", $pCondition=""){
        $result = array();
        if(is_array($pArray)){
            foreach($pArray as $temp_array){
                if(is_object($temp_array)){
                    $temp_array = (array) $temp_array;
                }
                if((""!=$pCondition && $temp_array[$pCondition[0]]==$pCondition[1]) || ""==$pCondition) {
                    $result[] = (""==$pKey) ? $temp_array : isset($temp_array[$pKey]) ? $temp_array[$pKey] : "";
                }
            }
            return $result;
        }else{
            return false;
        }
    }

    /**
     * 获取二级地区
     * @return array
     */
    public function getSecondArea(){
        $areaList = $this->getAreaData();
        if($areaList){
            foreach($areaList as $val){
                if(strstr($val['area_code'],'0000')){
                    $data[] = $val;
                }
            }

            return $data;
        }
    }

    /**
     * 获取国内所有有效的城市
     */
    public function getAllValidCity(){
        $data = getRedis($this->redisDb)->get($this->valid_city_data);

        if(!$data){
            $data = $this->_getAllValidCity();
        } else {
            $data = unserialize($data);
        }

        return $data;
    }

    private function _getAllValidCity(){
        $sql = 'SELECT * FROM `cgf_area` WHERE area_code LIKE \'%00\' and area_code not LIKE \'%0000\'';
        $list = M()->query($sql);

        //var_dump($list);
        if($list){
            getRedis($this->redisDb)->set($this->valid_city_data,serialize($list));
        }

        return $list;
    }

    public function isAreaCodeExists($areacode){
        return M($this->tableName)->where(array('area_code'=>$areacode))->getField('name');
    }
}